import React, { useEffect, useRef } from "react";
import ReactDOM from "react-dom/client";

type ToastProps = {
  duration?: number;
  message: string;
  onClose?: (...args: any[]) => void;
};

const Toast: React.FC<ToastProps> = ({ duration = 1200, message, onClose }) => {
  const [visible, setVisible] = React.useState(true);
  const closeRef = useRef(onClose);

  useEffect(() => {
    const timer = setTimeout(() => {
      setVisible(false);
      closeRef.current?.();
    }, duration);
  }, [duration]);

  return (
    <div
      className="toast"
      style={{
        display: visible ? "block" : "none",
        padding: "10px 20px",
        background: "rgba(0, 0, 0, .6)",
        color: "white",
        position: "fixed",
        top: "8%",
        left: "50%",
        transform: "translate(-50%, 0%)",
        borderRadius: "3px",
        zIndex: 9999,
      }}
    >
      {message}
    </div>
  );
};

// eslint-disable-next-line
export const showToast = (function getShowToast() {
  let isShowing = false;
  const queue = [] as Array<ToastProps>;

  return function openToast(opts: string | ToastProps) {
    let options: ToastProps;
    if (typeof opts === "string") {
      options = {
        message: opts,
      };
    } else {
      options = opts;
    }

    if (isShowing) {
      queue.push(options);
      return;
    }

    let div = document.createElement("div");
    div.className = "toast-wrapper";
    document.body.append(div);
    const toastRoot = ReactDOM.createRoot(div);

    const onClose = () => {
      toastRoot.unmount();
      document.body.removeChild(div);
      div = null as any;
      isShowing = false;

      options.onClose?.();

      // only one toast
      if (queue.length) {
        openToast(queue.shift()!);
      }
    };

    toastRoot.render(<Toast {...options} onClose={onClose} />);
    isShowing = true;
  };
})();

export default Toast;
